package com.mindbodyonline.ironhide.Infrastructure.Extensions; import android.annotation.TargetApi; import android.os.SystemClock; import android.support.test.espresso.UiController; import android.util.Log; import static com.android.support.test.deps.guava.base.Preconditions.checkNotNull; import static com.mindbodyonline.ironhide.Infrastructure.Extensions.Zoomer.Status.FAILURE; import static com.mindbodyonline.ironhide.Infrastructure.Extensions.Zoomer.Status.SUCCESS; /** * Executes different zoom types to given positions. */ @TargetApi(14) public enum Zoom implements Zoomer { /** zooms quickly between the co-ordinates. */ FAST { @Override public Status sendZoom(UiController uiController, float[][] startCoordinates, float[][] endCoordinates, float[] precision) { return sendLinearZoom(uiController, startCoordinates, endCoordinates, precision, ZOOM_FAST_DURATION_MS); } }, /** zooms deliberately slowly between the co-ordinates, to aid in visual debugging. */ SLOW { @Override public Status sendZoom(UiController uiController, float[][] startCoordinates, float[][] endCoordinates, float[] precision) { return sendLinearZoom(uiController, startCoordinates, endCoordinates, precision, ZOOM_SLOW_DURATION_MS); } }; /** The number of motion events to send for each zoom. */ private static final int ZOOM_EVENT_COUNT= 10; /** Length of time a "fast" zoom should last for, in milliseconds. */ private static final int ZOOM_FAST_DURATION_MS = 100; /** Length of time a "slow" zoom should last for, in milliseconds. */ private static final int ZOOM_SLOW_DURATION_MS = 1500; private static final String TAG = Zoom.class.getSimpleName(); private static float linearInterpolation(float alpha, float a, float b) { return (1 - alpha) * a + alpha * b; } private static float[][] linearInterpolation(float alpha, float[][] a, float[][] b) { return new float[][]{ new float[]{ linearInterpolation(alpha, a[0][0], b[0][0]), linearInterpolation(alpha, a[0][1], b[0][1]) }, new float[]{ linearInterpolation(alpha, a[1][0], b[1][0]), linearInterpolation(alpha, a[1][1], b[1][1]) } }; } private static Zoomer.Status sendLinearZoom(UiController uiController, float[][] startCoordinates, float[][] endCoordinates, float[] precision, int duration) { checkNotNull(uiController); checkNotNull(startCoordinates); checkNotNull(endCoordinates); checkNotNull(precision); ZoomMotionEvents manager = new ZoomMotionEvents(uiController, precision); boolean injectSuccess = manager.sendDownPair(startCoordinates); for (int i = 0; i < ZOOM_EVENT_COUNT; i++) { float alpha = (float)i / ZOOM_EVENT_COUNT; if (!manager.sendMovementPair(linearInterpolation(alpha, startCoordinates, endCoordinates))) { Log.e(TAG, "Injection of move event as part of the zoom failed. Sending cancel event."); manager.sendCancelPair(linearInterpolation(alpha, startCoordinates, endCoordinates)); return FAILURE; } long loopDuration = manager.downTime + (long)(alpha * duration) - SystemClock.uptimeMillis(); if (loopDuration > ZoomMotionEvents.MIN_LOOP_TIME) uiController.loopMainThreadForAtLeast(loopDuration); } injectSuccess = injectSuccess && manager.sendUpPair(endCoordinates); if (injectSuccess) return SUCCESS; else { Log.e(TAG, "Injection of up event as part of the zoom failed. Sending cancel event."); manager.sendCancelPair(endCoordinates); return FAILURE; } } }